package com.apanal.qlife.common.util;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.apanal.qlife.common.constants.Constants;
import com.apanal.qlife.common.util.DateUtil.DateStyle;

/**
 * Excel工具类<br>
 * Excel2003-07一个工作表最多可有65536行,最多可有256列，列用英文字母A—Z，AA—AZ，BA—BZ，……，IA—IV表示,
 * 一个工作簿中最多含有255个工作表，默认情况下是三个工作表； Excel 2007及以后版本，一个工作表最多可有1048576行，16384列；
 * 
 * @author shuliangxing
 * 
 * @date 2015-1-14上午11:39:17
 */
public class ExcelUtils {

	private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);

	public static final String EXCEL_2003 = "excel2003";

	public static final String EXCEL_2007 = "excel2007";

	public static final int EXCEL_2003_MAX_ROW = 65536;

	public static final int EXCEL_2003_MAX_column = 256;

	public static final int EXCEL_2007_MAX_ROW = 1048576;

	public static final int EXCEL_2007_MAX_column = 16384;

	/**
	 * 写excel文件,不支持大数据情况
	 * 
	 * @param titles
	 *            表头数组
	 * @param width
	 *            列宽度数组
	 * @param list
	 *            数据集合
	 * @param sheetName
	 *            sheet名称
	 * @param type
	 *            excel类型
	 * @param outputStream
	 *            输出流
	 * @throws IOException
	 */
	public static void writeExcel(String[] titles, int[] width,
			List<List<String>> list, String sheetName, String type,
			OutputStream outputStream) throws IOException {
		Workbook workBook = null;
		// 创建一个workbook 对应一个excel应用文件
		if (EXCEL_2007.equalsIgnoreCase(type)) {
			workBook = new XSSFWorkbook();
		} else {
			workBook = new HSSFWorkbook();
		}

		if (StringUtils.isEmpty(sheetName)) {
			sheetName = "Sheet1";
		}
		// 在workbook中添加一个sheet,对应Excel文件中的sheet
		Sheet sheet = workBook.createSheet(sheetName);
		// 冻结第一行
		sheet.createFreezePane(0, 1, 0, 1);

		CellStyle headStyle = getHeadStyle(workBook);
		CellStyle bodyStyle = getBodyStyle(workBook);
		// 构建表头
		Row headRow = sheet.createRow(0);
		// 设置高度
		headRow.setHeightInPoints(30);

		// 单元格
		Cell cell = null;
		// 构建表头数据
		for (int i = 0; i < titles.length; i++) {
			if (width != null && i < width.length) {
				// 设置单元格宽度
				sheet.setColumnWidth(i, width[i]);
			}

			cell = headRow.createCell(i);
			cell.setCellStyle(headStyle);
			cell.setCellValue(titles[i]);
		}

		// 构建表体数据
		if (list != null && list.size() > 0) {
			for (int j = 0; j < list.size(); j++) {
				Row bodyRow = sheet.createRow(j + 1);
				List<String> itemList = list.get(j);
				int index = 0;

				for (String item : itemList) {
					cell = bodyRow.createCell(index++);
					cell.setCellStyle(bodyStyle);
					cell.setCellValue(item);
				}
			}
		}
		try {
			workBook.write(outputStream);
			outputStream.flush();
			outputStream.close();
		} catch (IOException e) {
			throw e;
		} finally {
			try {
				outputStream.close();
			} catch (IOException e) {
			}
		}

	}

	/**
	 * 写excel文件,不支持大数据情况
	 * 
	 * @param titles
	 *            表头数组
	 * @param width
	 *            列宽度数组
	 * @param list
	 *            数据集合
	 * @param fileName
	 *            文件名称
	 * @param sheetName
	 *            sheet名称
	 * @param type
	 *            excel类型
	 * @param outputStream
	 *            输出流
	 * @throws IOException
	 */
	public static void writeExcel(String[] titles, int[] width,
			List<List<String>> list, String fileName, String sheetName,
			String type, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		ServletOutputStream outputStream = response.getOutputStream();
		// 文件名加上日期
		fileName += DateUtil.dateToString(new Date(), DateStyle.YYYYMMDD);
		// 去掉空格
		fileName = fileName.replaceAll(" ", "");
		// IE的话，通过URLEncoder对filename进行UTF8编码。
		// 而其他的浏览器（firefox、chrome、safari、opera），则要通过字节转换成ISO8859-1了
		if (WebUtils.isIe(request)) {
			fileName = URLEncoder.encode(fileName, "UTF-8");
		} else {
			fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
		}

		// 组装附件名称和格式
		String contentDisposition = "attachment; filename=" + fileName;
		if (EXCEL_2007.equalsIgnoreCase(type)) {
			contentDisposition += ".xlsx";
		}
		// 默认导出2003,高版本可以打开低版本
		else {
			contentDisposition += ".xls";
		}

		request.setCharacterEncoding("UTF-8");
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("application/octet-stream;charset=ISO8859_1");
		response.setHeader("Content-disposition", contentDisposition);

		writeExcel(titles, width, list, sheetName, type, outputStream);
	}

	/**
	 * 合并单元格后给合并后的单元格加边框
	 * 
	 * @param region
	 * @param cs
	 */
	public static void setRegionStyle(Sheet sheet, CellRangeAddress region,
			CellStyle cs) {

		int toprowNum = region.getFirstRow();
		for (int i = toprowNum; i <= region.getLastRow(); i++) {
			Row row = sheet.getRow(i);
			for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {
				Cell cell = row.getCell(j);// XSSFCellUtil.getCell(row,
											// (short) j);
				cell.setCellStyle(cs);
			}
		}
	}

	/**
	 * 设置表头的单元格样式
	 * 
	 * @return
	 */
	public static CellStyle getHeadStyle(Workbook wb) {
		// 创建单元格样式
		CellStyle cellStyle = wb.createCellStyle();
		// 设置单元格的背景颜色为淡蓝色
		cellStyle.setFillForegroundColor(HSSFColor.PALE_BLUE.index);
		cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
		// 设置单元格居中对齐
		cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		// 设置单元格垂直居中对齐
		cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		// 创建单元格内容显示不下时自动换行
		cellStyle.setWrapText(true);
		// 设置单元格字体样式
		Font font = wb.createFont();
		// 设置字体加粗
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
		font.setFontName("宋体");
		// font.setFontHeight((short) 200);
		cellStyle.setFont(font);
		// 设置单元格边框为细线条
		// cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
		// cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
		// cellStyle.setBorderRight(CellStyle.BORDER_THIN);
		// cellStyle.setBorderTop(CellStyle.BORDER_THIN);
		return cellStyle;
	}

	/**
	 * 设置表体的单元格样式
	 * 
	 * @return
	 */
	public static CellStyle getBodyStyle(Workbook wb) {
		// 创建单元格样式
		CellStyle cellStyle = wb.createCellStyle();
		// 设置单元格居中对齐
		// cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		// 设置单元格垂直居中对齐
		cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		// 创建单元格内容显示不下时自动换行
		cellStyle.setWrapText(true);
		// 设置单元格字体样式
		Font font = wb.createFont();
		// 设置字体加粗
		// font.setBoldweight(Font.BOLDWEIGHT_BOLD);
		font.setFontName("宋体");
		// font.setFontHeight((short) 200);
		cellStyle.setFont(font);
		// 设置单元格边框为细线条
		// cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
		// cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
		// cellStyle.setBorderRight(CellStyle.BORDER_THIN);
		// cellStyle.setBorderTop(CellStyle.BORDER_THIN);
		return cellStyle;
	}

	// 解决类型问题，获得数值
	public static String getValue(Cell cell) {
		String value = "";
		if (null == cell) {
			return value;
		}
		switch (cell.getCellType()) {
		// 数值型
		case Cell.CELL_TYPE_NUMERIC:
			if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
				// 如果是date类型则 ，获取该cell的date值，并进行格式化
				Date date = org.apache.poi.ss.usermodel.DateUtil
						.getJavaDate(cell.getNumericCellValue());
				SimpleDateFormat format = new SimpleDateFormat(
						Constants.DATE_FORMAT);
				value = format.format(date);
			} else {// 纯数字
				value = String.valueOf(cell.getNumericCellValue());
				// 解决1234.0 去掉后面的.0
				if (null != value && !"".equals(value.trim())) {
					String[] item = value.split("[.]");
					if (1 < item.length && "0".equals(item[1])) {
						value = item[0];
					}
				}
			}
			break;
		// 字符串类型
		case Cell.CELL_TYPE_STRING:
			value = cell.getStringCellValue().toString();
			break;
		// 公式类型
		case Cell.CELL_TYPE_FORMULA:
			// 读公式计算值
			value = String.valueOf(cell.getNumericCellValue());
			if (value.equals("NaN")) {// 如果获取的数据值为非法值,则转换为获取字符串
				value = cell.getStringCellValue().toString();
			}
			break;
		// 布尔类型
		case Cell.CELL_TYPE_BOOLEAN:
			value = " " + cell.getBooleanCellValue();
			break;
		// 空值
		case Cell.CELL_TYPE_BLANK:
			value = "";
			log.error("excel出现空值");
			break;
		// 故障
		case Cell.CELL_TYPE_ERROR:
			value = "";
			log.error("解析excel出现故障");
			break;
		default:
			value = cell.getStringCellValue().toString();
		}
		if ("null".endsWith(value.trim())) {
			value = "";
		}
		return value;
	}

}
